module;
#include <iterator>

export module Code_20_3_3;




template<typename FROM, typename TO>
struct IsConvertibleHelper
{
private:
    static void aux(TO);
    template<typename F,
        typename = decltype(aux(std::declval<F>()))>
    static std::true_type test(void*);
    template<typename>
    static std::false_type test(...);

public:
    using Type = decltype(test<FROM>(nullptr));
};

template<typename FROM, typename TO>
struct IsConvertibleT : IsConvertibleHelper<FROM, TO>::Type
{
};

template<typename FROM, typename TO>
using IsConvertible = typename IsConvertibleT<FROM, TO>::Type;



template<bool, typename T = void>
struct EnableIfT {};

template< typename T>
struct EnableIfT<true, T>
{
    using Type = T;
};

template<bool Cond, typename T = void>
using EnableIf = typename EnableIfT<Cond, T>::Type;

template<typename Iterator>
constexpr bool IsRandomAccessIterator = IsConvertible< typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>;

template<typename Iterator>
constexpr bool IsBidirectionalIterator = IsConvertible< typename std::iterator_traits<Iterator>::iterator_category, std::bidirectional_iterator_tag>;

template<typename Iterator, typename Distance>
void advanceIter(Iterator& x, Distance n) 
{
    if constexpr (IsRandomAccessIterator<Iterator>) 
    {
        // implementation for random access iterators:
        x += n; // constant time
    }
    else if constexpr (IsBidirectionalIterator<Iterator>) 
    {
        // implementation for bidirectional iterators:
        if (n > 0)
        {
            for (; n > 0; ++x, --n)  //linear time for positive n
            { 
            }
        }
        else {
            for (; n < 0; --x, ++n)  //linear time for negative n
            {
            }
        }
    }
    else 
    {
        // implementation for all other iterators that are at least input iterators:
        if (n < 0) 
        {
            throw "advanceIter(): invalid iterator category for negative n";
        }
        while (n > 0) //linear time for positive n only
        { 
            ++x;
            --n;
        }
    }
}

export
namespace Code_20_3_3 {

    void run()
    {

    }
}
